home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / diag / iozon115.zip / IOZONE.C next >
Text File  |  1992-05-30  |  35KB  |  1,116 lines

  1. char *help[] = {
  2.   "       'IO Zone' Benchmark Program",
  3.   " ",
  4.   "       Author: Bill Norcott (norcott_bill@tandem.com)",
  5.   "               1060 Hyde Avenue",
  6.   "               San Jose, CA  95129",
  7.   " ",
  8.   "  Copyright 1991, 1992   William D. Norcott",
  9.   " ",
  10.   "  License to freely use and distribute this software is hereby granted ",
  11.   "  by the author, subject to the condition that this copyright notice ",
  12.   "  remains intact.  The author retains the exclusive right to publish ",
  13.   "  derivative works based on this work, including, but not limited to, ",
  14.   "  revised versions of this work",
  15.   " ",
  16.   "  This test writes a X MEGABYTE sequential file in Y byte chunks, then",
  17.   "  rewinds it  and reads it back.  [The size of the file should be",
  18.   "  big enough to factor out the effect of any disk cache.].  Finally,",
  19.   "  IOZONE deletes the temporary file",
  20.   "        ",
  21.   "  The file is written (filling any cache buffers), and then read.  If the",
  22.   "  cache is >= X MB, then most if not all the reads will be satisfied from",
  23.   "  the cache.  However, if it is less than or equal to .5X MB, then NONE of",
  24.   "  the reads will be satisfied from the cache.  This is becase after the ",
  25.   "  file is written, a .5X MB cache will contain the upper .5 MB of the test",
  26.   "  file, but we will start reading from the beginning of the file (data",
  27.   "  which is no longer in the cache)",
  28.   "        ",
  29.   "  In order for this to be a fair test, the length of the test file must",
  30.   "  be AT LEAST 2X the amount of disk cache memory for your system.  If",
  31.   "  not, you are really testing the speed at which your CPU can read blocks",
  32.   "  out of the cache (not a fair test)",
  33.   "        ",
  34.   "  IOZONE does not normally test the raw I/O speed of your disk or system.",
  35.   "  It tests the speed of sequential I/O to actual files.  Therefore, this",
  36.   "  measurement factors in the efficiency of you machines file system,",
  37.   "  operating system, C compiler, and C runtime library.  It produces a ",
  38.   "  measurement which is the number of bytes per second that your system",
  39.   "  can read or write to a file.  ",
  40.   " ",
  41.   "  You use IOZONE to test the I/O speed of a UNIX 'RAW DEVICE' such",
  42.   "  as a tape drive, hard disk drive, floppy disk drive, etc.  To do this,",
  43.   "  you must define the symbol NO_DELETE when you compile IOZONE.  If you",
  44.   "  fail to define NO_DELETE, IOZONE will treat the raw device as a ",
  45.   "  temporary file, and WILL DELETE THE RAW DEVICE after the test completes!",
  46.   "  When testing raw devices, any UNIX buffer caching is bypassed.  IOZONE",
  47.   "  still is using the read()/write() system calls, so you are not quite",
  48.   "  testing the device at the low level of say, disk controller diagnostics.",
  49.   "  On the other hand, that kind of testing is highly system- and device-",
  50.   "  specific, and my goal for IOZONE has been to build a highly portable",
  51.   "  benchmark -- not one which is tied to a particular operating system or",
  52.   "  hardware configuration.  In practice, I have tested raw disk and tape",
  53.   "  peripherals and the results are very close to the manufacturer's specs",
  54.   "  for those devices.",
  55.   " ",
  56.   "  For V1.06, IOZONE adds the 'auto test' feature.  This is activated",
  57.   "  by the command:  'iozone auto' .  The auto test runs IOZONE repeatedly  ",
  58.   "  using record sizes from 512 to 8192 bytes, and file sizes from 1 to 16",
  59.   "  megabytes.  It creates a table of results.",
  60.   "        ",
  61.   "  For V1.06, IOZONE lets you specify the number of file system sizes and      ",
  62.   "  record lengths to test when using auto mode.  Define the constants",
  63.   "  MEGABYTES_ITER_LIMIT and RECLEN_ITER_LIMIT as seen below      ",
  64.   "        ",
  65.   "  For V1.09 you can show the development help by typing 'iozone help'",
  66.   "        ",
  67.   "  For V1.10 IOzone traps SIGINT (user interrupt) and SIGTERM",
  68.   "  (kill from shell) signals and deletes the temporary file",
  69.   "        ",
  70.   "  For V1.11 IOzone requires no compilation flags for AIX",
  71.   "  Also, come miscellaneous cleanups have been made to the source",
  72.   "        ",
  73.   "  For V1.12 IOzone support has been added for the MIPS RISCos,",
  74.   "  Tandem Non-StopUX, and Tandem GUARDIAN 90 operating systems.",
  75.   "  IOzone is now a 'Conforming POSIX.1 Application'  (IEEE Std 1003.1-1988)",
  76.   "        ",
  77.   "  For V1.14 IOzone supports Next and QNX systems.  It also prints out",
  78.   "  the name of the operating system when run.  There is now the option",
  79.   "  to force IOzone to flush all writes to disk via fsync()",
  80.   "  Defining USE_FSYNC will make IOzone include in its measurements the time",
  81.   "  it takes to actually write the data onto disk, as opposed to",
  82.   "  just writing into the system cache.  BSD UNIX and SVR4 support fsync(),",
  83.   "  but SVR3 and generic POSIX systems do not.  I have enabled USE_FSYNC",
  84.   "  for the systems which support it",
  85.   "        ",
  86.   "  For V1.14, we now officially support AT&T SVR4.  It has worked just",
  87.   "  fine using SVR4 with previous versions of IOzone.  Also, for systems",
  88.   "  which use the times() function, we calculate the 'base time' the first",
  89.   "  time we ever call time_so_far(), then subtract this time from all",
  90.   "  future measurements.  This increases the precision of our measurement",
  91.   "  and fixes a loss-of-precision problem which occurred on some systems",
  92.   "        ",
  93.   "  For V1.15, add the NO_DELETE symbol.  If you define NO_DELETE during",
  94.   "  the compilation (e.g., for UNIX systems compile with cc -DNO_DELETE),",
  95.   "  IOzone will not delete the 'temporary' file which it reads & writes.",
  96.   "  This is REQUIRED when testing RAW DEVICES such as disks and tape drives!",
  97.   "        ",
  98.   " ",
  99.   "  This program has been ported and tested on the following computer",
  100.   "  operating systems:",
  101.   " ",
  102.   "    Vendor             Operating System    Notes on compiling IOzone",
  103.   "    -------------------------------------------------------------------------",
  104.   "    Apollo             Domain/OS           no cc switches -- BSD domain",
  105.   "    AT&T               UNIX System V Release 4",
  106.   "    AT&T 6386WGS       AT&T UNIX 5.3.2     define SYSTYPE_SYSV",
  107.   "    Generic AT&T       UNIX System V R3    may need cc -DSVR3",
  108.   "    Convergent         Unisys/AT&T Sys5r3  cc -DCONVERGENT -o iozone iozone.c",
  109.   "    Digital Equipment  ULTRIX V4.1 ",
  110.   "    Digital Equipment  VAX/VMS V5.4        see below **         ",
  111.   "    Digital Equipment  VAX/VMS (POSIX) ",
  112.   "    Hewlett-Packard    HP-UX 7.05",
  113.   "    IBM                AIX Ver. 3 rel. 1",
  114.   "    Interactive        UNIX System V R3    ",
  115.   "    Microsoft          MS-DOS 3.3          tested Borland, Microsoft C",
  116.   "    MIPS               RISCos 4.52",
  117.   "    NeXt               NeXt OS 2.x",
  118.   "    OSF                OSF/1",
  119.   "    Portable!          POSIX 1003.1-1988   may need to define _POSIX_SOURCE ",
  120.   "    QNX                QNX 4.0",
  121.   "    SCO                UNIX System V/386 3.2.2",
  122.   "    SCO                XENIX 2.3",
  123.   "    SCO                XENIX 3.2",
  124.   "    Silicon Graphics   UNIX                cc -DSGI -o iozone iozone.c",
  125.   "    Sony Microsystems  UNIX                same as MIPS",
  126.   "    Sun Microsystems   SUNOS 4.1.1",
  127.   "    Tandem Computers   GUARDIAN 90         1. call the source file IOZONEC",
  128.   "                                           2. C/IN IOZONEC/IOZONE;RUNNABLE",
  129.   "                                           3. RUN IOZONE",
  130.   "    Tandem Computers   Non-Stop UX",
  131.   "        ",
  132.   "    ** for VMS, define iozone as a foreign command via this DCL command:       ",
  133.   " ",
  134.   "       $IOZONE :== $SYS$DISK:[]IOZONE.EXE      ",
  135.   " ",
  136.   "       this lets you pass the command line arguments to IOZONE",
  137.   " ",
  138.   "  Acknowledgements to the following persons for their feedback on IOzone:       ",
  139.   " ",
  140.   "  Andy Puchrik, Michael D. Lawler, Krishna E. Bera, Sam Drake, John H. Hartman, ",
  141.   "  Ted Lyszczarz, Bill Metzenthen, Jody Winston, Clarence Dold, Axel",
  142.   "  Dan Hildebrand, Joe Nordman, Bob Fritz, Jeff Johnson",
  143.   "        ",
  144.   "  --- MODIFICATION HISTORY:",
  145.   " ",
  146.   " ",
  147.   "    3/7/91 William D. Norcott (Bill.Norcott@nuo.mts.dec.com)",
  148.   "                               created",
  149.   " ",
  150.   "    3/22/91 Bill Norcott       tested on OSF/1 ... it works",
  151.   " ",
  152.   "    3/24/91 Bill Norcott       V1.02 -- use calloc in TURBOC to",
  153.   "                                       fix bug with their malloc",
  154.   " ",
  155.   "    3/25/91 Bill Norcott       V1.03 -- add ifdef for XENIX",
  156.   "                                       ",
  157.   "    3/27/91 Bill Norcott       V1.04 -- Includes for SCO UNIX",
  158.   "                                       ",
  159.   "    4/26/91 Bill Norcott       V1.05 -- support AIX and SUNos, check",
  160.   "                                       length of read() and write()",
  161.   "    4/26/91 Bill Norcott       V1.06 -- tabulate results of a series ",
  162.   "                                       of tests",
  163.   "    5/17/91 Bill Norcott       V1.07 -- use time() for VMS",
  164.   "    5/20/91 Bill Norcott       V1.08 -- use %ld for Turbo C and",
  165.   "                                       use #ifdef sun to bypass",
  166.   "                                       inclusion of limits.h",
  167.   "    6/19/91 Bill Norcott       V1.09 -- rid #elif to support HP-UX and ",
  168.   "                                       Silicon Graphics UNIX, and",
  169.   "                                       add #ifdef SGI",
  170.   "                                       add #ifdef CONVERGENT",
  171.   "                                       for Convergent Technologies",
  172.   "                                       also add help option",
  173.   "    7/2/91 Bill Norcott        V1.10 -- delete file if get SIGINT",
  174.   "                                       or SIGTERM",
  175.   "    8/20/91 Bill Norcott       V1.11 -- require no flags with AIX",
  176.   "    11/4/91 Bill Norcott       V1.12 -- support MIPS RISCos",
  177.   "                                         Tandem NonStop-UX, and",
  178.   "                                        IEEE Std POSIX 1003.1-1988",
  179.   "    12/4/91 Bill Norcott       V1.13 -- support NeXT; tell host OS type",
  180.   "    1/23/92 Bill Norcott      V1.14 -- support QNX & use calloc() for buffer",
  181.   "    5/1/92 Bill Norcott      V1.15 -- support SVR4; fix loss of precision",
  182.   "                                       in times() function.  ",
  183.   "                                       support Interactive UNIX",
  184.   "                                       detect ANSI if no O/S",
  185.   "                                       Also, define for generic SVR3",
  186.   "                                       Apollo Domain/OS",
  187.   "                                       Define NO_DELETE and iozone wont",
  188.   "                                       delete the temp file.  Needed to",
  189.   "                                       test raw devices without deleting",
  190.   "                                       them",
  191.   "" };
  192.  
  193. /******************************************************************
  194.  
  195.   INCLUDE FILES (system-dependent)
  196.  
  197.   ******************************************************************/
  198. /*
  199. V1.15 -- Define the symbol NO_DELETE if you plan to use IOzone to test
  200. the speed of UNIX raw devices such as disk- and tape drives.  This will
  201. tell IOzone NOT to delete the file after the test completes
  202. */
  203. /* #define NO_DELETE */
  204. /*
  205. V1.15 -- If you have a generic System V R3 not on my list of supported
  206. systems, define SVR3 when you compile IOzone. If you have to use this, please
  207. send tell me what preprocessor symbols your C compiler defines which
  208. will help me test for your particular system... do a 'man cc' on a
  209. UNIX system to check, or just do a 'man cc > cc.txt' and mail me
  210. cc.txt
  211. */
  212. /*  Define the following if you have a generic System V R3 system which
  213. is not one of the specific versions listed above
  214. */
  215. /* #define SVR3 */
  216. #ifdef SVR3
  217. #ifndef OS_TYPE
  218. #define OS_TYPE "'Generic' UNIX System V Release 3 -- vendor unknown"
  219. #endif
  220. #include <fcntl.h>
  221. #include <sys/types.h>
  222. #define SysVtime
  223. #endif
  224. /* V1.15 -- add Apollo Domain O/S to the list -- it also worked in previous
  225. versions, now it will print its identity
  226. */
  227. #ifdef apollo
  228. #ifndef OS_TYPE
  229. #define OS_TYPE "Apollo Domain/OS -- using BSD libraries"
  230. #define BSDtime
  231. #define USE_FSYNC
  232. #endif
  233. #endif
  234.  
  235. /* V1.14 -- use calloc instead of stack for buffer, on all platforms */
  236. #define usecalloc
  237. /*
  238. V1.14b -- check for ultrix which uses sysconf in newer POSIX version
  239. but uses BSD-style time in the pre-POSIX versions
  240. V1.15 use fsync() for ultrix even though V4.2 will pick up other options
  241. from POSIX
  242. */
  243. #ifdef ultrix
  244. #ifndef OS_TYPE
  245. #define OS_TYPE "ULTRIX 4.0 or earlier"
  246. #define BSDtime
  247. #define USE_FSYNC
  248. #endif
  249. #endif
  250. /* V1.13 -- support NeXT by treating it like a Sun... Thanks Axel! */
  251. #ifdef __NeXT__
  252. #ifndef OS_TYPE
  253. #define OS_TYPE "NeXT OS"
  254. #endif
  255. #define sun
  256. #endif
  257. /*
  258.   define nolimits if your system has no limits.h.  Sun's don't but I
  259.   take care of this explicitly beginning with V1.08 of IOzone.
  260.   */
  261. #ifdef sun
  262. #ifndef OS_TYPE
  263. #define OS_TYPE "SunOS"
  264. #endif
  265. #define nolimits
  266. #define BSDtime
  267. #define USE_FSYNC
  268. #endif
  269. /* V1.09 -- Silicon Graphics compile with -DSGI  */
  270. #ifdef SGI
  271. #ifndef OS_TYPE
  272. #define OS_TYPE "Silicon Graphics"
  273. #endif
  274. #define nolimits
  275. #define BSDtime
  276. #endif
  277.  
  278. /* V1.13 For MIPS RISC/OS and Tandem NonStop-UX*/
  279. #ifdef SYSTYPE_BSD43
  280. #define bsd4_3
  281. #ifndef OS_TYPE
  282. #define OS_TYPE "MIPS RISC/os (BSD 4.3 libraries)"
  283. #endif
  284. #endif
  285.  
  286. #ifdef SYSTYPE_SYSV
  287. #include <sys/utsname.h>
  288. #define nolimits
  289. #ifdef T_NONSTOP
  290. #define OS_TYPE "TANDEM NonStop-UX (System V libraries)"
  291. #endif
  292. #ifndef OS_TYPE
  293. #define OS_TYPE "MIPS RISC/os (System V libraries)"
  294. #endif
  295. #define SysVtime
  296. #include <sys/types.h>
  297. #include <sys/times.h>
  298. #include <sys/fcntl.h>
  299. #endif
  300. /* V1.14 -- define nolimits and BSDtime for Xenix 2.3.3 */
  301. /* incl definitions of O_* flags for XENIX */
  302. #ifdef M_UNIX
  303. #define SCOunix
  304. #else
  305. #ifdef M_XENIX
  306. #define SCOxenix
  307. #endif
  308. #endif
  309.  
  310. /* SCO Unix System V */
  311. #ifdef SCOunix
  312. #define OS_TYPE "SCO UNIX System V/386"
  313. #include <sys/types.h>
  314. #include <sys/fcntl.h>
  315. #endif
  316.  
  317. #ifdef SCOxenix
  318. #ifdef XENIX_2_3
  319. #define OS_TYPE "SCO XENIX 2.3.x"
  320. #define BSDtime
  321. #else
  322. #define OS_TYPE "SCO XENIX 3.x"
  323. #define SysVtime
  324. #endif
  325. #endif
  326.  
  327. /* V1.12 -- test for POSIX-conformant operating system; requires limits.h */
  328. /*
  329. V1.15 -- I have been told that there is a problem in the times() POSIX
  330. function in Ultrix V4.1 and greater.  It seems to return the time in
  331. whole seconds (expressed in terms of clock ticks) instead of correctly
  332. returning the elapsed time in clock ticks ALTHOUGH POSIX 1003.1-1988
  333. and ISO 9945 CLEARLY STATE that "times() shall return the elapsed real
  334. time, in clock ticks."
  335.  
  336. This means calling times() twice in the same second and subtracting
  337. the two values, produces an answer of 0, which IOzone detects as an error.
  338.  
  339. I thought I had a problem in V1.14 under Ultrix with loss of precision,
  340. i.e. taking the difference of two large floating point numbers,
  341. but the problem seems be that Ultrix times() *inherently* has a
  342. loss of precision, so my "fix" can't fix the broken system call.
  343. Until they fix it in Ultrix I am going to use BSD-style everything
  344. for Ultrix
  345. */
  346. #ifndef nolimits
  347.  
  348. #include <limits.h>
  349. #ifdef _POSIX_ARG_MAX
  350. #ifndef ultrix
  351. #ifndef OS_TYPE
  352. #define OS_TYPE "POSIX 1003.1-1988"
  353. #endif
  354. #define isposix
  355. #undef USE_FSYNC
  356. #else
  357. /* It's ultrix disguised as POSIX; still use BSD calls until they fix it */
  358. #undef OS_TYPE
  359. #define OS_TYPE "ULTRIX 4.1 or later"
  360. #endif
  361. #endif
  362. #endif
  363.  
  364. /* Tandem's GUARDIAN operating system */
  365. #include <stdio.h>
  366. #ifdef __TANDEM
  367. #ifndef OS_TYPE
  368. #define OS_TYPE "TANDEM GUARDIAN 90"
  369. #endif
  370. #define nosignals
  371. #define ANSItime
  372. #define ANSI_MAIN
  373. #include <fcntl.h>
  374. #include <stdlib.h>
  375. #include <string.h>
  376. #include <time.h>
  377. #endif
  378. #ifndef nosignals
  379. #include <signal.h>
  380. #endif
  381. #ifdef    __MSDOS__        /* Turbo C define this way for PCs... */
  382. #define MSDOS            /* Microsoft C defines this */
  383. #endif
  384. /* VMS and MS-DOS both have ANSI C compilers and use rand()/srand() */
  385. #ifdef    VMS_POSIX
  386. #undef     VMS
  387. #define ANSI_RANDOM    1
  388. #endif
  389. #ifdef    MSDOS
  390. #define ANSI_RANDOM    1
  391. #endif
  392. /* Convergent Technologies M680xx based with Unisys/AT&T Sys5r3 */
  393. #ifdef CONVERGENT
  394. #ifndef OS_TYPE
  395. #define OS_TYPE "Convergent Technologies"
  396. #endif
  397. #include <fcntl.h>
  398. #define SysVtime
  399. #endif
  400. /* Interactive UNIX System V Release 3.2 */
  401. #ifdef isc386
  402. #ifndef OS_TYPE
  403. #define OS_TYPE "Interactive UNIX System V/386"
  404. #endif
  405. #include <fcntl.h>
  406. #define SysVtime
  407. #endif
  408.  
  409. /* V1.11 -- With the following includes, AIX no longer requires -Dunix */
  410. #ifdef _AIX
  411. #ifndef OS_TYPE
  412. #define OS_TYPE "AIX"
  413. #endif
  414. #include <fcntl.h>
  415. #include <sys/time.h>
  416. #endif
  417.  
  418. #if defined(VMS)
  419. #ifndef OS_TYPE
  420. #define OS_TYPE "VAX/VMS"
  421. #endif
  422. #define ANSItime
  423. #define ANSI_RANDOM    1
  424. #include    <math.h>
  425. #include    <unixio.h>
  426. #include    <ssdef.h>
  427. #include    <file.h>
  428. #include    <time.h>
  429.  
  430. #else
  431. /* ... either MSDOS, POSIX, or a generic non-POSIX UNIX */
  432. #ifdef MSDOS
  433. #ifndef OS_TYPE
  434. #define OS_TYPE "MS-DOS"
  435. #endif
  436. #define usecalloc
  437. #include <fcntl.h>
  438. #include <time.h>
  439. #else
  440. /* nope, not MS-DOS, try POSIX */
  441. #ifdef isposix
  442. #include <time.h>
  443. #include <sys/times.h>
  444. #include <fcntl.h>
  445. #include <unistd.h>
  446. #else
  447. #ifdef unix
  448. #include <fcntl.h>
  449. #else
  450. #define O_RDONLY 0
  451. #endif
  452. #endif
  453. #endif
  454. #endif
  455.  
  456. /* for systems with System V-style time, define SysVtime */
  457. #ifdef M_SYSV
  458. #define SysVtime
  459. #endif
  460.  
  461. /* for systems with BSD style time, define BSDtime */
  462. #ifdef bsd4_2
  463. #define USE_FSYNC
  464. #ifndef OS_TYPE
  465. #define OS_TYPE "BSD 4.2"
  466. #endif
  467. #define BSDtime
  468. #endif
  469. #ifdef bsd4_3
  470. #define USE_FSYNC
  471. #ifndef OS_TYPE
  472. #define OS_TYPE "BSD 4.3"
  473. #endif
  474. #define BSDtime
  475. #endif
  476. /*
  477. If we made it this far and still don't know which operating system
  478. we are running, check if we at least have ANSI C so we can do some
  479. kind of time functions.  On the other hand, if we know what O/S
  480. we are running use the (more precise) time routines for that O/S,
  481. even if we do have ANSI C.  If we don't know what O/S we are and
  482. we don't have ANSI C, but we are some flavor of UNIX, I will use
  483. time() which any UNIX will have.  For the worst case we are not
  484. any form of UNIX nor a supported proprietary O/S, and we don't have
  485. ANSI C either,    one of two things will happen:
  486. 1. If you define NOTIMER then you will have to use a stopwatch
  487. 2. If NOTIMER not defined, we will assume we can use time()
  488. */
  489. #ifndef OS_TYPE
  490. #ifdef __STDC__
  491. #define OS_TYPE "ANSI C"
  492. #define ANSItime
  493. #include    <time.h>
  494. #endif
  495. #endif
  496.  
  497. #ifndef OS_TYPE
  498. #ifdef unix
  499. #define OS_TYPE "UNIX (can't tell if System V or BSD) -- using time()"
  500. #define ANSItime
  501. #include    <time.h>
  502. #endif
  503. #endif
  504.  
  505. #ifndef OS_TYPE
  506. #if NOTIMER
  507. #define OS_TYPE "System type unknown & not ANSI C -- disabling timing"
  508. #define noclock 1
  509. #else
  510. #define OS_TYPE "System type unknown & not ANSI C -- using time()"
  511. #define ANSItime
  512. #include    <time.h>
  513. #endif
  514. #endif
  515.  
  516. #ifdef SysVtime
  517. #undef BSDtime
  518. #include <sys/times.h>
  519. #include <sys/param.h>
  520. #ifndef CLK_TCK
  521. #define CLK_TCK HZ
  522. #endif
  523. #endif
  524.  
  525. #ifdef BSDtime
  526. #undef SysVtime
  527. #include <sys/time.h>
  528. #endif
  529.  
  530. /******************************************************************
  531.  
  532.   DEFINED CONSTANTS
  533.  
  534.   ******************************************************************/
  535. /* Define NULL in case we don't have it... */
  536. #ifndef NULL
  537. #define NULL 0
  538. #endif
  539. /*
  540.   V1.14: Define ONETEST to run a single test at runtime as the default
  541.   V1.14: Define AUTOTEST to run in auto test mode as the default
  542.   i.e. the behavior of IOzone when it is invoked with no arguments.  ONETEST
  543.   makes IOzone run a single test using a 1 MB file and 512 byte records.
  544.   AUTOTEST causes IOzone to use auto test mode.
  545.   For compatibility with previous versions of IOZONE, ONETEST is the default
  546.   setting
  547. */
  548. #define ONETEST 1
  549. #ifndef ONETEST
  550. #define AUTOTEST
  551. #endif
  552.  
  553. /*
  554.   V1.14: Define USE_FSYNC to force writes to disk during the write phase
  555.   BSD and BSD-derived UNIX variants and also SVR4 are known to have fsync
  556.   UNIX).  After the file is written and before it is closed, call fsync()
  557.   to force the data to be written from cache to disk.  This (mostly) cancels
  558.   the fact that systems with a lot of memory for cache buffers or memory
  559.   mapping display artificially high transfer rates during the write phase
  560.   of IOzone, because the data never makes it onto the disk.
  561.  
  562. */
  563. #if 0
  564. #define USE_FSYNC
  565. #endif
  566.  
  567. #define MEGABYTES 1            /* number of megabytes in file */
  568. #define RECLEN 512            /* number of bytes in a record */
  569. #define FILESIZE 1048576        /*size of file in bytes*/
  570. #define NUMRECS 2048            /* number of records */
  571. #define MAXBUFFERSIZE 16*1024        /*maximum buffer size*/
  572. #define MINBUFFERSIZE 128
  573. #define TOOFAST 10
  574. #define IOZONE_USAGE \
  575. "\tUsage:\tiozone [megabytes] [record_length_in_bytes] [[path]filename]\n\t\tiozone auto\n\t\tiozone help\n\n"
  576. #define THISVERSION "V1.15"
  577. #define RELEASEDATE "5/1/92"
  578.   /* Define only one of the following two.  All modern operating systems
  579.      have time functions so let TIME be defined */
  580. #ifndef noclock
  581. #define TIME 1
  582. #endif
  583.  
  584. #define MAXNAMESIZE 1000        /* max # of characters in filename */
  585. #define CONTROL_STRING1 "\t%-8ld%-8ld%-20ld%-20ld\n"
  586. #define CONTROL_STRING2 "\t%-8s%-8s%-20s%-20s\n"
  587.   /*
  588.     For 'auto mode', these defines determine the number of iterations
  589.     to perform for both the file size and the record length.
  590.     I.e., if MEGABYTES_ITER_LIMIT = 5 use 1, 2, 4, 8 & 16 megabyte files
  591.     if RECLEN_ITER_LIMIT = 5 use 512, 1024, 2048, 4096 & 8192 byte records
  592.     */
  593. #define MEGABYTES_ITER_LIMIT 5
  594. #define RECLEN_ITER_LIMIT 5
  595. /******************************************************************
  596.  
  597.   MACRO DEFINITIONS
  598.  
  599.   ******************************************************************/
  600. #define abs(X) ( (X) < 0 ? (-(X)) : (X) )  /* Absolute value of X */
  601.   /******************************************************************
  602.  
  603.     FUNCTION DECLARATIONS
  604.  
  605.  
  606.     ******************************************************************/
  607. void auto_test();        /* perform automatic test series */
  608. void show_help();        /* show development help*/
  609. double time_so_far();        /* time since start of program */
  610. void signal_handler();        /* clean up if user interrupts us */
  611. /******************************************************************
  612.  
  613.   GLOBAL VARIABLES
  614.  
  615.   ******************************************************************/
  616. int auto_mode;
  617. char filename [MAXNAMESIZE];        /* name of temporary file */
  618. /******************************************************************
  619.  
  620.   MAIN -- entry point
  621.  
  622.   ******************************************************************/
  623. #ifdef ANSI_MAIN
  624. int
  625. main(int argc, char *argv[], char *env[])    /* main body of code */
  626. #else
  627. int
  628.      main(argc,argv)
  629.      int argc;
  630.      char *argv[];
  631. #endif
  632. {
  633. #ifdef ANSI_MAIN
  634.   char *fooenv;
  635. #endif
  636.   int fd;
  637.   char *default_filename;
  638.  
  639. #ifdef    usecalloc
  640.   char *buffer;
  641. #else
  642.   char buffer [MAXBUFFERSIZE];          /*a temporary data buffer*/
  643. #endif
  644.   unsigned i;
  645.   unsigned megabytes = MEGABYTES;
  646.   unsigned reclen = RECLEN;
  647.   unsigned long filesize;
  648.   unsigned long numrecs;
  649.   unsigned long thisrec;
  650. #ifdef TIME
  651.   unsigned long filebytes;
  652.   unsigned long readrate, writerate;
  653.   unsigned goodmegs;
  654.   unsigned goodrecl;
  655.   double starttime;
  656.   double writetime, readtime;
  657.   double totaltime;
  658. #endif
  659. #ifdef usecalloc
  660.     buffer = (char *) calloc(1, MAXBUFFERSIZE);
  661. #endif
  662.  
  663. #if defined (ANSI_MAIN)
  664.   fooenv= env[0];    /* dummy so we make some use of env (to avoid warnings) */
  665. #endif
  666.  
  667. #if defined (__TANDEM)
  668.   default_filename ="IOZONET"; /* TANDEM GUARDIAN 90 has max 8 char filenames */
  669. #else
  670.   default_filename ="iozone.tmp"; /*default name of temporary file*/
  671. #endif
  672.   if (!auto_mode)
  673.     {
  674.       printf("\n\tIOZONE: Performance Test of Sequential File I/O  --  %s (%s)\n",
  675.          THISVERSION, RELEASEDATE);
  676.       printf("\t\tBy Bill Norcott\n\n");
  677. #ifdef USE_FSYNC
  678.       printf("\tOperating System: %s -- using fsync()\n\n", OS_TYPE);
  679. #else
  680.       printf("\tOperating System: %s\n\n", OS_TYPE);
  681. #endif
  682. #ifndef nosignals
  683.       signal(SIGINT, signal_handler);       /* handle user interrupt */
  684.       signal(SIGTERM, signal_handler);       /* handle kill from shell */
  685. #endif
  686.     }
  687.   strcpy(filename,default_filename);
  688.   switch (argc) {
  689.   case 1:     /* no args, take all defaults */
  690.     printf(IOZONE_USAGE);
  691. #ifdef AUTOTEST
  692.     auto_mode = 1;
  693.     auto_test();
  694.     printf("Completed series of tests\n");
  695.     exit(0);
  696. #endif
  697.     break;
  698.   case 2:     /* <megabytes|filename> */
  699.     i = (unsigned) abs(atoi(argv[1]));
  700.     if (i) {
  701.       megabytes = i;
  702.     } else {
  703.       /*
  704.     'Auto mode' will be enabled if the first command line argument is
  705.     the word 'auto'.  This will trigger a series of tests
  706.     */
  707.       if ( (strcmp(argv[1], "auto") == 0) ||
  708.       (strcmp(argv[1], "AUTO") == 0) )
  709.     {
  710.       auto_mode = 1;
  711.       auto_test();
  712.       printf("Completed series of tests\n");
  713.       exit(0);
  714.     } else {
  715.       auto_mode = 0;
  716.     }
  717.       if ( (strcmp(argv[1], "help") == 0) ||
  718.       (strcmp(argv[1], "HELP") == 0) )
  719.     {
  720.       show_help();
  721.       exit(0);
  722.     }
  723.       strcpy(filename,argv[1]);
  724.     }
  725.     break;
  726.   case 3:     /* <megabytes> <reclen|filename> */
  727.     megabytes = (unsigned) atoi(argv[1]);
  728.     if (atoi(argv[2])) {
  729.       reclen = atoi(argv[2]);
  730.     } else {
  731.       strcpy(filename,argv[2]);
  732.     }
  733.     break;
  734.   case 4:     /* <megabytes> <reclen> <filename> */
  735.     megabytes = (unsigned) atoi(argv[1]);
  736.     reclen = atoi(argv[2]);
  737.     strcpy(filename,argv[3]);
  738.     break;
  739.   default:
  740.     printf("IOZONE: bad usage\n");
  741.     printf(IOZONE_USAGE);
  742.     exit(1);
  743.  
  744.   }
  745.   if (!auto_mode)
  746.     {
  747.       printf("\tSend comments to:\tnorcott_bill@tandem.com\n\n");
  748.     }
  749.   filesize = (unsigned long) (1024L*1024L*megabytes);
  750.   numrecs =  filesize/(unsigned long) reclen;
  751.   if (reclen >    MAXBUFFERSIZE) {
  752.     printf("<Error: Maximum record length is %d bytes\n", MAXBUFFERSIZE);
  753.     exit(1);
  754.   }
  755.   if (reclen < MINBUFFERSIZE) {
  756.     printf("Error: Minimum record length is %d bytes\n", MINBUFFERSIZE);
  757.     exit(1);
  758.   }
  759.   if (!auto_mode)
  760.     {
  761.       printf("\tIOZONE writes a %ld Megabyte sequential file consisting of\n",
  762.          megabytes);
  763.       printf("\t%ld records which are each %ld bytes in length.\n",
  764.          numrecs, reclen);
  765.       printf("\tIt then reads the file.  It prints the bytes-per-second\n");
  766.       printf("\trate at which the computer can read and write files.\n\n");
  767.       printf("\nWriting the %ld Megabyte file, '%s'...", megabytes, filename);
  768.     }
  769.  
  770. #if defined (__TANDEM)
  771.   /*
  772.     Tandem's GUARDIAN preallocates file space based on primary- and secondary extents.
  773.     The last 2 parameters to open are the sizes of the primary- and secondary extents,
  774.     in blocks which are 2K bytes each.    After the primary extent is filled, GUARDIAN
  775.     allocates up to 15 additional extents, one at a time.
  776.     */
  777. #define SPECIAL_CREAT
  778. #define PRI_EXT_BLOCKS 1024
  779. #define SEC_EXT_BLOCKS 1024
  780.   if((fd = creat(filename, 0640,
  781.          PRI_EXT_BLOCKS, SEC_EXT_BLOCKS))<0){
  782.     printf("Cannot create temporary file: %s\n", filename);
  783.     exit(1);
  784.   }
  785. #endif
  786. #ifndef SPECIAL_CREAT
  787.   if((fd = creat(filename, 0640))<0){
  788.     printf("Cannot create temporary file: %s\n", filename);
  789.     exit(1);
  790.   }
  791. #endif
  792. #ifdef TIME
  793.   starttime = time_so_far();
  794. #endif
  795. #ifndef TIME
  796.   printf("\nstart timing\n");
  797. #endif
  798.   for(thisrec=0; thisrec<numrecs; thisrec++){
  799. #ifndef DEBUG_ME
  800.     if(write(fd, buffer, (unsigned) reclen) != reclen)
  801.       {
  802.     printf("Error writing block %d\n", thisrec);
  803.     perror("iozone");
  804.     close(fd);
  805. #ifndef VMS
  806. #ifndef NO_DELETE
  807.     unlink(filename);   /* delete the file */
  808. #endif
  809.     /*stop timer*/
  810. #endif
  811.     exit(1);
  812.       }
  813. #endif
  814.   }
  815. #ifdef USE_FSYNC
  816.   fsync(fd);
  817. #endif
  818. #ifdef TIME
  819.   writetime = time_so_far() - starttime;
  820.   if (!auto_mode)
  821.     {
  822.       printf("%f seconds", writetime);
  823.     }
  824. #endif
  825. #ifndef TIME
  826.   printf("\nstop timing\n");
  827. #endif
  828.   close(fd);
  829. #if defined (VMS)
  830. #define SPECIAL_OPEN_READ
  831.   if((fd = open(filename, O_RDONLY, 0640))<0){
  832.     printf("Cannot open temporary file for read\n");
  833.     exit(1);
  834.   }
  835. #endif
  836.  
  837. #ifdef MSDOS
  838. #define SPECIAL_OPEN_READ
  839.   if((fd = open(filename, O_RDONLY, 0640))<0){
  840.     printf("Cannot open temporary file for read\n");
  841.     exit(1);
  842.   }
  843. #endif
  844.  
  845.   /*
  846.     'Generic' case, compiled if no operating system-specific case was invoked
  847.     */
  848. #ifndef SPECIAL_OPEN_READ
  849.   if((fd = open(filename, O_RDONLY))<0){
  850.     printf("Cannot open temporary file for read\n");
  851.     exit(1);
  852.   }
  853. #endif
  854.  
  855.  
  856.  
  857.   /*start timing*/
  858.   if (!auto_mode)
  859.     {
  860.       printf("\nReading the file...");
  861.     }
  862. #ifndef TIME
  863.   printf("\nstart timing\n");
  864. #endif
  865. #ifdef TIME
  866.   starttime = time_so_far();
  867. #endif
  868.   for(thisrec=0; thisrec<numrecs; thisrec++) {
  869. #ifndef DEBUG_ME
  870.     if(read(fd, buffer, (unsigned) reclen) != reclen)
  871.       {
  872.     printf("Error reading block %d\n", thisrec);
  873.     exit(1);
  874.       }
  875. #endif
  876.   }
  877. #ifndef TIME
  878.   printf("\nstop timing\n");
  879. #endif
  880. #ifdef TIME
  881.   readtime = time_so_far() - starttime;
  882.   if (!auto_mode)
  883.     {
  884.       printf("%f seconds\n", readtime);
  885.     }
  886. #ifdef DEBUG_ME
  887.   readtime = 1;
  888.   writetime = 1;
  889. #endif
  890.   if(readtime!=0)
  891.     {
  892.       filebytes = numrecs* (unsigned long) reclen;
  893.       readrate = (unsigned long) ((double) filebytes / readtime);
  894.       writerate = (unsigned long) ((double) filebytes / writetime);
  895.       if (auto_mode)
  896.     {
  897.       printf(CONTROL_STRING1,
  898.          megabytes,
  899.          reclen,
  900.          writerate,
  901.          readrate);
  902.  
  903.     } else {
  904.       printf("\nIOZONE performance measurements:\n");
  905.       printf("\t%ld bytes/second for writing the file\n", writerate);
  906.       printf("\t%ld bytes/second for reading the file\n", readrate);
  907.       totaltime = readtime + writetime;
  908.       if (totaltime < TOOFAST)
  909.         {
  910.           goodmegs = (TOOFAST/totaltime)*2*megabytes;
  911.           printf("\nThe test completed too quickly to give a good result\n");
  912.           printf("You will get a more precise measure of this machine's\n");
  913.           printf("performance by re-running IOZONE using the command:\n");
  914.           printf("\n\tiozone %ld ", goodmegs);
  915.           printf("\t(i.e., file size = %ld megabytes)\n", goodmegs);
  916.         }
  917.     }
  918.     } else {
  919.       goodrecl = reclen/2;
  920.       printf("\nI/O error during read.  Try again with the command:\n");
  921.       printf("\n\tiozone %ld %ld ", megabytes,  goodrecl);
  922.       printf("\t(i.e. record size = %ld bytes)\n",  goodrecl);
  923.     }
  924. #endif
  925.   close(fd);
  926. #ifndef VMS
  927. #ifndef NO_DELETE
  928.   unlink(filename);   /* delete the file */
  929. #endif
  930.   /*stop timer*/
  931. #endif
  932. #ifdef    usecalloc
  933.   free(buffer);       /* deallocate the memory */
  934. #endif
  935. #ifdef VMS
  936.   return SS$_NORMAL;
  937. #else
  938.   return 0;
  939. #endif
  940. }
  941. /******************************************************************
  942.  
  943.   SHOW_HELP -- show development help of this program
  944.  
  945.   ******************************************************************/
  946. void
  947.   show_help()
  948. {
  949.   int i;
  950.   printf("IOZONE: help mode\n\n");
  951.   for(i=0; strlen(help[i]); i++)
  952.     {
  953.       printf("%s\n", help[i]);
  954.     }
  955. }
  956. /******************************************************************
  957.  
  958.   SIGNAL_HANDLER -- clean up if user interrupts the program
  959.  
  960.   ******************************************************************/
  961. void
  962.   signal_handler()
  963. {
  964.   printf("\nIOZONE: interrupted\n\n");
  965. #ifndef VMS
  966. #ifndef NO_DELETE
  967.   printf("deleting file: %s\n", filename);
  968.   unlink(filename);   /* delete the file */
  969. #endif
  970. #endif
  971.   printf("exiting IOzone\n\n");
  972.   exit(0);
  973. }
  974. /******************************************************************
  975.  
  976.   AUTO_TEST -- perform series of tests and tabulate results
  977.  
  978.   ******************************************************************/
  979. void
  980.   auto_test()
  981. {
  982.  
  983.   int megsi, recszi;
  984.   char megs[10];
  985.   char recsz[10];
  986.   int i,j;
  987.   int autoArgc = 3;
  988.   char *autoArgv[3];
  989.  
  990.   printf("IOZONE: auto-test mode\n\n");
  991.   printf(CONTROL_STRING2,
  992.      "MB",
  993.      "reclen",
  994.      "bytes/sec written",
  995.      "bytes/sec read");
  996.   autoArgv[0] = "IOzone auto-test";
  997.   autoArgv[1] = megs;
  998.   autoArgv[2] = recsz;
  999.   /*
  1000.     Start with file size of 1 megabyte and repeat the test MEGABYTES_ITER_LIMIT
  1001.     times.  Each time we run, the file size is doubled
  1002.     */
  1003.   for(i=0,megsi=1;i<MEGABYTES_ITER_LIMIT;i++,megsi*=2)
  1004.     {
  1005.       sprintf(megs, "%d", megsi);
  1006.       /*
  1007.     Start with record size of 512 bytes and repeat the test RECLEN_ITER_LIMIT
  1008.     times.    Each time we run, the record size is doubled
  1009.     */
  1010.       for (j=0,recszi=512;j<RECLEN_ITER_LIMIT;j++,recszi*=2)
  1011.     {
  1012.       sprintf(recsz, "%d", recszi);
  1013. #ifdef ANSI_MAIN
  1014.       main(autoArgc, autoArgv, NULL);
  1015. #else
  1016.       main(autoArgc, autoArgv);
  1017. #endif
  1018.     }
  1019.     }
  1020. }
  1021.  
  1022. #ifdef TIME
  1023. /******************************************************************
  1024.  
  1025.   TIME_SO_FAR -- return elapsed time
  1026.  
  1027.   5/17/91 Bill Norcott          V1.07 -- use time() for VMS
  1028.   The times() function in VMS returns proc & user CPU time in 10-millisecond
  1029.   ticks.  Instead, use time() which lacks the precision but gives clock
  1030.   time in seconds.
  1031.   V1.14 make val of type clock_t if we are dealing with POSIX
  1032.   V1.15 first time this is called, set base to initial number of clock
  1033.   ticks, then subtract this value from all subsequent calculations.  This
  1034.   will fix a loss of precision when times returns very big numbers;
  1035.  
  1036.   Here is what we check for (in order).  Each returns so we do not
  1037.   have to nest the #ifdefs -- should satisfy even the dumbest
  1038.   pre-processor.  Note that each has its own flavor of timekeeping
  1039.   1. ANSI C
  1040.   2. POSIX - with and without CLK_TCK defined
  1041.   3. System V variants
  1042.   4. MS-DOS
  1043.   5. BSD variants
  1044.   ******************************************************************/
  1045. double
  1046.   time_so_far()
  1047. {
  1048. #if defined(ANSItime)
  1049.   return (double) time(NULL);
  1050. #endif
  1051.  
  1052. #ifdef isposix
  1053.   {
  1054.     static clock_t base, val;
  1055.     struct tms tms;
  1056.  
  1057.     if (base == 0)
  1058.       {
  1059.     base = times(&tms);
  1060.     if (base == (clock_t) -1)
  1061.       {
  1062.         perror("times");
  1063.       }
  1064.       }
  1065.     val = times(&tms);
  1066.     if (val == (clock_t) -1)
  1067.       {
  1068.     perror("times");
  1069.       }
  1070.     val = val - base;
  1071. #ifndef CLK_TCK
  1072.     return ((double) val) / ((double) sysconf(_SC_CLK_TCK));
  1073. #else
  1074.     return ((double) val) / ((double) CLK_TCK);
  1075. #endif
  1076.   }
  1077. #endif
  1078.  
  1079. #ifdef SysVtime
  1080.   {
  1081.     static long base, val;
  1082.     struct tms tms;
  1083.  
  1084.     if (base == 0)
  1085.       {
  1086.     if ((base = times(&tms)) == -1)
  1087.       {
  1088.         perror("times");
  1089.       }
  1090.       }
  1091.     if ((val = times(&tms)) == -1)
  1092.       {
  1093.     perror("times");
  1094.       }
  1095.     val = val - base;
  1096.     return ((double) val) / ((double) CLK_TCK);
  1097.   }
  1098. #endif
  1099.  
  1100. #if defined(MSDOS)
  1101.   return ((double) clock()) / ((double) CLK_TCK);
  1102. #endif
  1103.  
  1104. #ifdef BSDtime
  1105.   {
  1106.     struct timeval tp;
  1107.  
  1108.     if (gettimeofday(&tp, (struct timezone *) NULL) == -1)
  1109.       perror("gettimeofday");
  1110.     return ((double) (tp.tv_sec)) +
  1111.       (((double) tp.tv_usec) / 1000000.0);
  1112.   }
  1113. #endif
  1114. }
  1115. #endif
  1116.